#include <stdio.h>

int _main()
{
	printf("hello world.\n");
	return 0;
}

// 上面的代码等效于：
char *SG3830[] = {"hello, world\n"};

int main()
{
	printf("%s", *SG3830);
	return 0;
}

#if 0
/*
 * intel
 */
0000000000001169 <_main>:
    1169:	f3 0f 1e fa          	endbr64 
    116d:	55                   	push   %rbp
    116e:	48 89 e5             	mov    %rsp,%rbp
    1171:	48 8d 3d 8c 0e 00 00 	lea    0xe8c(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>  // rdi="hello world.\n"
    1178:	e8 e3 fe ff ff       	callq  1060 <puts@plt>          // puts(rdi)
    117d:	b8 00 00 00 00       	mov    $0x0,%eax
    1182:	5d                   	pop    %rbp
    1183:	c3                   	retq   

0000000000001184 <main>:
    1184:	f3 0f 1e fa          	endbr64 
    1188:	55                   	push   %rbp
    1189:	48 89 e5             	mov    %rsp,%rbp
    118c:	48 8b 05 7d 2e 00 00 	mov    0x2e7d(%rip),%rax        # 4010 <SG3830>
    1193:	48 89 c6             	mov    %rax,%rsi                // rsi="hello world.\n"
    1196:	48 8d 3d 82 0e 00 00 	lea    0xe82(%rip),%rdi        # 201f <_IO_stdin_used+0x1f> // rdi="%s"
    119d:	b8 00 00 00 00       	mov    $0x0,%eax
    11a2:	e8 c9 fe ff ff       	callq  1070 <printf@plt>        // printf(rdi, rsi)
    11a7:	b8 00 00 00 00       	mov    $0x0,%eax
    11ac:	5d                   	pop    %rbp
    11ad:	c3                   	retq   
    11ae:	66 90                	xchg   %ax,%ax

/*
 * arm
 */
00000000004005ac <_main>:
  4005ac:	a9bf7bfd 	stp	x29, x30, [sp, #-16]!
  4005b0:	910003fd 	mov	x29, sp
  4005b4:	90000000 	adrp	x0, 400000 <_init-0x428>
  4005b8:	911aa000 	add	x0, x0, #0x6a8              // x0="hello world.\n"
  4005bc:	97ffffb5 	bl	400490 <puts@plt>           // puts(x0)
  4005c0:	52800000 	mov	w0, #0x0                   	// #0
  4005c4:	a8c17bfd 	ldp	x29, x30, [sp], #16
  4005c8:	d65f03c0 	ret

00000000004005cc <main>:
  4005cc:	a9bf7bfd 	stp	x29, x30, [sp, #-16]!
  4005d0:	910003fd 	mov	x29, sp
  4005d4:	b0000080 	adrp	x0, 411000 <__libc_start_main@GLIBC_2.17>
  4005d8:	9100e000 	add	x0, x0, #0x38
  4005dc:	f9400001 	ldr	x1, [x0]        // x1="hello world.\n"
  4005e0:	90000000 	adrp	x0, 400000 <_init-0x428>
  4005e4:	911b2000 	add	x0, x0, #0x6c8  // x0="%s"
  4005e8:	97ffffae 	bl	4004a0 <printf@plt> // printf(x0, x1)
  4005ec:	52800000 	mov	w0, #0x0                   	// #0
  4005f0:	a8c17bfd 	ldp	x29, x30, [sp], #16
  4005f4:	d65f03c0 	ret


#endif

#if 0
/*
 *  intel
 */
	xor eax, eax
	mov eax, 0
	两条指令结果相同，但xor 异或运算的opcode较短。

	也有一些编译器使用 sub eax, eax 把eax置0。

/*
 * gcc
 */
main 	proc near
var_10 	= dword ptr - 10h

	push ebp
	mov ebp, esp
	and esp, fffffff0	# 令栈地址(ESP的值)向16字节边界对齐(成为16的整数倍)
	sub esp, 10
	mov eax, offset HelloWord	; "hello, world\n"字符串在数据段地址(指针)存储到EAX
	mov [esp+10+var_10], eax	; 再把它存储在数据栈里
	call _printf
	mov eax, 0
	leave
	retn

main endp

	如钩地址位没有对齐，那么CPU可能需要访问两次内存才能获得栈内数据。

	sub esp, 10	在栈中分配0x10 bytes，即16字节。程序只会用到4字节空间。但是因为
编译器对栈地址(ESP)进行了16字节对齐，所以每次都会分配16字节的空间。

	leave 指令，等效于“MOV ESP， EBP” 和 “POP EBP” 两条指令。


/*
 * X86-64
 */
	SG2989 db  'hello, world', 00h

	main proc
		sub rsp, 40
		lea rcx, offset flat:SG2989
		call printf
		xor eax, eax
		add rsp, 40
		ret 0
	main endp

	main函数的返回值是整数类型的零，但是出于兼容性和可移植性的考虑，C语言的编译器仍将使用32位的零。换而言之，即使是64位的
	应用程序，在程序结束时EAX的值是零，而RAX的值不一定会是零。

	此时，数据栈的对应空间里仍有40字节的数据。这部分数据空间有个专用的名词，即阴影空间(shadow space)。


/*
 * gcc x86-64
 */
	.string "hello,world\n"
	main:
		sub rsp, 8
		mov edi, offset flat:.LC0	; hello,world
		xor eax, eax				; number of vector registers passed
		call printf
		xor eax, eax
		add rsp, 8
		ret

	需要注意的是，64位汇编指令MOV在写放R-寄存器的低32位地址位的时候即对E-寄存器进行写操作的时候，
    会同时清除R-寄存器中的高32位地址位。

/*
 * arm
 */
	main
		stmfd sp!, {r4, lr}
		aor ro, aHellowWorld	; "hello, world"
		bl _2printf
		mov r0, #0
		ldmfd sp!, {r4, pc}

/*
 * arm 64
 */
	stp x29, x30, [sp, #-16]!
	mov x29, sp
	adrp x0, 40000<_init+0x3b8>
	add x0, x0, #0x648
	bl 40040 <puts@plt>
	mov wo, #0x0
	ldp x29, x30, [sp], #16
	ret

#endif 

